package com.atguigu.gmall.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl extends ServiceImpl<OrderInfoMapper,OrderInfo>implements OrderService {

    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RabbitService rabbitService;
    @Value("${ware.url}")
    private String WARE_URL;

    @Override
    public Long saveOrderInfo(OrderInfo orderInfo) {
        try {
            orderInfo.sumTotalAmount();
            orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
            //赋值第三方交易编号
            String outTradeNo = "ATGUIGU" + System.currentTimeMillis() + new Random().nextInt(1000);
            orderInfo.setOutTradeNo(outTradeNo);
            orderInfo.setTradeBody("电商支付-买个帽子");
            orderInfo.setOperateTime(new Date());
            //设置过期时间
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.DATE,1);
            orderInfo.setExpireTime(calendar.getTime());

            orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
            orderInfoMapper.insert(orderInfo);
            List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
            if (!CollectionUtils.isEmpty(orderDetailList)) {
                orderDetailList.forEach(orderDetail -> {
                    orderDetail.setOrderId(orderInfo.getId());
                    orderDetailMapper.insert(orderDetail);
                });
            }
            //发送延迟消息
            rabbitService.sendDelayMsg(MqConst.EXCHANGE_DIRECT_ORDER_CANCEL, MqConst.ROUTING_ORDER_CANCEL, orderInfo.getId(), MqConst.DELAY_TIME);

            return orderInfo.getId();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }


    }

    /**
     * 生成流水号
     * @param userId
     * @return
     */
    @Override
    public String getTradeCode(String userId) {
        String tradeKey = "user:" + userId + ":tradecode";
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        redisTemplate.opsForValue().set(tradeKey,uuid);
        return uuid;
    }

    @Override
    public Boolean checkTradeCode(String userId, String tradeCode) {
        String tradeKey = "user:" + userId + ":tradecode";
        String redisTradCode = (String) redisTemplate.opsForValue().get(tradeKey);
        return tradeCode.equals(redisTradCode);
    }

    @Override
    public void deleteTradeCode(String userId) {
        String tradeKey = "user:" + userId + ":tradecode";
        redisTemplate.delete(tradeKey);
    }

    @Override
    public boolean checkStock(Long skuId, Integer skuNum) {
        String result = HttpClientUtil.doGet(WARE_URL + "/hasStock?skuId=" + skuId + "&num=" + skuNum);
        return "1".equals(result);
    }

    @Override
    public IPage<OrderInfo> getOrder(Page<OrderInfo> cartInfoPage, String userId, String orderStatus) {
        IPage<OrderInfo> orderInfoList = orderInfoMapper.selectOrder(cartInfoPage, userId, orderStatus);
        if (orderInfoList!=null) {
            orderInfoList.getRecords().forEach(orderInfo->{
                String statusNameByStatus = OrderStatus.getStatusNameByStatus(orderInfo.getOrderStatus());
                orderInfo.setOrderStatusName(statusNameByStatus);
            });
        }

        return orderInfoList;
    }

    /**
     * 订单过期，修改订单状态
     * @param orderId
     */
    @Override
    public void execExpiredOrder(Long orderId) {
        updateOrder(orderId, ProcessStatus.CLOSED);
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE, MqConst.ROUTING_PAYMENT_CLOSE, orderId);
    }

    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        if (orderInfo != null) {
            LambdaQueryWrapper<OrderDetail> orderDetailLambdaQueryWrapper = new LambdaQueryWrapper<>();
            orderDetailLambdaQueryWrapper.eq(OrderDetail::getOrderId, orderId);
            List<OrderDetail> orderDetailList = orderDetailMapper.selectList(orderDetailLambdaQueryWrapper);
            orderInfo.setOrderDetailList(orderDetailList);
        }
        return orderInfo;
    }

    public void updateOrder(Long orderId, ProcessStatus processStatus) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setId(orderId);
        orderInfo.setProcessStatus(processStatus.name());
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
        orderInfoMapper.updateById(orderInfo);
    }

    @Override
    public void sendDeductStockMsg(Long orderId) {
        //修改订单状态
        updateOrder(orderId, ProcessStatus.WAITING_DELEVER);
        OrderInfo orderInfo = getOrderInfo(orderId);
        //封装返回数据
        Map<String, Object> wareMap = initWareOrder(orderInfo);
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_WARE_STOCK, MqConst.ROUTING_WARE_STOCK, JSON.toJSONString(wareMap));
    }

    public Map<String, Object> initWareOrder(OrderInfo orderInfo) {
        Map<String, Object> mapResult = new HashMap<>();
        //从orderInfo获取封装相关订单信息
        mapResult.put("orderId", orderInfo.getId());
        mapResult.put("consignee", orderInfo.getConsignee());
        mapResult.put("consigneeTel", orderInfo.getConsigneeTel());
        mapResult.put("orderComment", orderInfo.getOrderComment());
        mapResult.put("orderBody", orderInfo.getTradeBody());
        mapResult.put("deliveryAddress", orderInfo.getDeliveryAddress());
        mapResult.put("paymentWay", "2");
        mapResult.put("wareId", orderInfo.getWareId());

        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        List<HashMap<String, Object>> orderDetailMapList = orderDetailList.stream().map(orderDetail -> {
            HashMap<String, Object> detailMap = new HashMap<>();
            detailMap.put("skuId", orderDetail.getSkuId());
            detailMap.put("skuNum", orderDetail.getSkuNum());
            detailMap.put("skuName", orderDetail.getSkuName());
            return detailMap;
        }).collect(Collectors.toList());
        mapResult.put("details", orderDetailMapList);
        return mapResult;
    }

    @Override
    public List<OrderInfo> spilt(String orderId, String wareSkuMap) {
        List<OrderInfo> orderInfoList = new ArrayList<>();

        //获取原始订单
        OrderInfo orderInfoOrigin = orderInfoMapper.selectById(Long.parseLong(orderId));
        List<Map> maps = JSONObject.parseArray(wareSkuMap, Map.class);
        if (!CollectionUtils.isEmpty(maps)) {
            maps.forEach(map -> {
                String wareId = (String) map.get("wareId");
                List<String> skuList = (List<String>) map.get("skuIds");
                OrderInfo subOrderInfo = new OrderInfo();
                subOrderInfo.setWareId(wareId);
                subOrderInfo.setParentOrderId(Long.parseLong(orderId));
                BeanUtils.copyProperties(orderInfoOrigin,subOrderInfo);
                subOrderInfo.setId(null);
                //获取订单全部明细
                List<OrderDetail> orderDetailList = orderInfoOrigin.getOrderDetailList();
                List<OrderDetail> subOrderDetailList = orderDetailList.stream().filter(orderDetail -> skuList.contains(orderDetail.getSkuId().toString())).collect(Collectors.toList());
                subOrderInfo.setOrderDetailList(subOrderDetailList);
                subOrderInfo.sumTotalAmount();
                saveOrderInfo(subOrderInfo);
                orderInfoList.add(subOrderInfo);
            });
        }
        updateOrder(Long.parseLong(orderId),ProcessStatus.SPLIT);

        return orderInfoList;
    }

    @Override
    public void execExpiredOrder(Long orderId, String flag) {
        updateOrder(orderId, ProcessStatus.CLOSED);
        if ("2".equals(flag)) {
            rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE, MqConst.ROUTING_PAYMENT_CLOSE, orderId);

        }
    }


}
